#ifndef POOLALLOCATER_H_
#define POOLALLOCATER_H_


/*
 *	<p>	PoolAllocater Stragy </p>
 *	@author:	Kenvi.Luo
 *	@email:		kenvi.luo@gmail.com
 *	@date:		2007/08/06
 *	@modify:	N/A
 *	----------------------------
 *	@samples:
 *		using namepsace FURY::STRAGY;
 *		...;
 *		PoolAllcater<Product*> allocater;
 *		Product *product = allocater.allocater();
 *		allocater.free(product);
 */
 

#include "../threadsafe/Guard.h"
#include "../threadsafe/CriticalLock.h"
#include <deque>
  
using namespace std;
  
namespace FURY
{
	 namespace STRAGY
	 {
		 template<typename T, typename Lock = CriticalLock, int once_allocate_size = 4, int max_allocate_size = 128	>
		 struct PoolAllocater
		 {
				deque<T*>	m_objPool;
 				Lock m_lock;
 				int	m_dead;
 			public:
 				PoolAllocater()
 				{
 					m_dead = 0;
				};

				~PoolAllocater()
				{
					for (deque<T*>::iterator iter = m_objPool.begin(); iter != m_objPool.end(); iter++)
					{
						T* t = *iter;
						t->release();
						delete t;
					}
					m_objPool.clear();
				};

 				T* allocate()
 				{
					T* obj = NULL;
 					Guard<Lock> guard(m_lock);
 					try
 					{
	 					if (m_objPool.size()==0)
	 					{
							if (m_dead>=max_allocate_size)
								return NULL;
	 						
	 						for (int i=0;i<once_allocate_size;i++)
	 							m_objPool.push_back(new T);
	 					}
	 					obj = m_objPool.front();
	 					m_objPool.pop_front();
	 					m_dead++;
 					} catch (...)
 					{
 						exit(0);
 					}
					return obj;
 				};

 				void free(T* obj)
 				{
					Guard<Lock> guard(m_lock);
 					if (obj!=NULL)
 					{
	 					obj->release();
						m_objPool.push_back(obj);
	 					m_dead--;
 					}
 				};
		 };
	 };
};

#endif /*POOLALLOCATER_H_*/
